#include <sys/socket.h>
#include <netinet/in.h>

#include <cstdlib>

#include <iostream>

#include "ClientManager.h"
#include "Config.h"
#include "ConfigManager.h"
#include "RequestHandler.h"
#include "SortLastGenerator.h"

#include "cbsocket/CBSocket.h"
#include "cbsocket/DefaultCallback.h"
#include "cbsocket/LineParser.h"
#include "cbsocket/Listener.h"

static cbsocket::CBSocket server;
static session_mgr::ConfigManager manager;

static cbsocket::AbstractCallback* responserMaker(int fd)
{
    using namespace cbsocket;
    using namespace session_mgr;
    RequestHandler *handler = new RequestHandler(&manager);
    DefaultCallback *cb = new DefaultCallback(fd, new LineParser(handler));
    handler->setSocket(cb);
    return cb;
}

int main(int argc, char *argv[])
{
    using namespace std;
    using namespace session_mgr;
    using namespace cbsocket;
    
    char const* configPath = NULL;
    
    if(argc != 2)
    {
        char const* defaultConfig = "session.cfg";
        clog << "Using default config \"" << defaultConfig << "\"" << endl;
        configPath = defaultConfig;
    }
    else
        configPath = argv[1];
    
    try
    {
        getConfig().load(configPath);
    }
    catch(char const* message)
    {
        cerr << "Cannot load config file, error message:\n";
        cerr << message << endl;
        return EXIT_FAILURE;
    }
    
    manager.registerGenerator<SortLastGenerator>("SortLast");
    
    sockaddr_in addr;
    addr.sin_family= AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(getConfig().getListenPort());
    int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    bind(fd, (sockaddr*)&addr, sizeof(addr));
    listen(fd, 5);
    
    server.addSocket(fd, new Listener(fd, &server, responserMaker));
    server.run();
    
    return 0;
}
